/**
 * @author: zouye<yzyngz@foxmail.com>
 * @date: 2022-01-04 23:01:06
 * @copyright: zouye<yzyngz@foxmail.com>
 */
package com.yeah.voice.recognition.service;

import java.io.File;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StreamUtils;

import com.yeah.voice.recognition.common.Properties;
import com.yeah.voice.recognition.entity.TbMarkData;
import com.yeah.voice.recognition.entity.TbMarkPeople;
import com.yeah.voice.recognition.entity.TbPeopleAnswerCount;
import com.yeah.voice.recognition.entity.TbWavData;
import com.yeah.voice.recognition.mapper.TbMarkDataMapper;
import com.yeah.voice.recognition.mapper.TbMarkPeopleMapper;
import com.yeah.voice.recognition.mapper.TbPeopleAnswerCountMapper;
//import com.yeah.voice.recognition.mapper.TbPeopleMarkAuditMapper;
import com.yeah.voice.recognition.mapper.TbWavDataMapper;


/**
 *
 */
@Service
@Transactional
public class VoiceService {
	@Autowired
	private Properties properties;
	
	@Autowired
	private TbMarkDataMapper tbMarkDataMapper;
	
	@Autowired
	private TbMarkPeopleMapper tbMarkPeopleMapper;
	
	@Autowired
	private TbWavDataMapper tbWavDataMapper;
	
	@Autowired
	private TbPeopleAnswerCountMapper tbPeopleAnswerCountMapper;
	
	/**
	 * 同一个人多次标记，避免重复重现已经被他标记过的音频；不同的人标记，优先让他们标记被标记次数最少的音频
	 * @return
	 */
	public synchronized TbWavData getMinMarkedCountWav(Integer peopleId) {
		tbWavDataMapper.resetOutdateIsMarking(properties.getResetIsMarkingAfterMinute() == null ? 5 : properties.getResetIsMarkingAfterMinute());

		TbWavData tbWavData = tbWavDataMapper.getMinMarkedCountWav(peopleId);
//		tbWavDataMapper.updateIsMarking(Integer.valueOf(tbWavData.getId()), 1);
		if (tbWavData != null) {
			tbWavDataMapper.updateIsMarking(Integer.valueOf(tbWavData.getId()), 1);
		}
		return tbWavData;
	}

	public TbWavData getWavFileByName(String wavFileName) {
		return tbWavDataMapper.getByName(wavFileName);
	}


	public boolean hasWavFile() {
		return tbWavDataMapper.hasWavFile();
	}
	
	/**
	 * 保存标记数据，音频标记计数 +1
	 * @param data
	 */
	public void saveMark(TbMarkData data) {
		tbMarkDataMapper.insert(data);


		// 验证用的音频，is_marking 标记永远为 1，确保自动获取音频时不会拿到它
		boolean needResetIsMarking = true;
		if (properties.getValidVoiceName() != null && !properties.getValidVoiceName().equals("")) {
			TbWavData tbWavData = tbWavDataMapper.getByName(properties.getValidVoiceName());
			if (tbWavData != null && tbWavData.getId().equals(data.getWavId().toString())) {
				needResetIsMarking = false;
			}
		}

		if (needResetIsMarking) {
			tbWavDataMapper.updateIsMarking(data.getWavId(), 0);
		}


		tbWavDataMapper.updateMarkedCountById(data.getWavId());
		
		// 标记第一条音频，就认为该用户用完了一次回答数量
		if (data.getCurrentMarkIndex() == 1) {
//			TbPeopleAnswerCount count = tbPeopleAnswerCountMapper.getByPeopleId(data.getPeopleId());
			TbMarkPeople people = tbMarkPeopleMapper.getById(data.getPeopleId());
			TbPeopleAnswerCount count = tbPeopleAnswerCountMapper.getByPhone(people.getPhone());

			if (count == null) {
//				count = new TbPeopleAnswerCount(data.getPeopleId(), 1);
				count = new TbPeopleAnswerCount(people.getPhone(), 1);
				tbPeopleAnswerCountMapper.insert(count);
			} else {
				count.setAnswerCount(count.getAnswerCount() + 1);
				tbPeopleAnswerCountMapper.updateAnswerCount(count);
			}
		}
	}
	
	/**
	 * 根据手机号判断用户是否还能继续标记
	 * @param phone
	 * @return
	 */
	public boolean checkCanAnswerByPhone(String phone) {
		TbPeopleAnswerCount count = tbPeopleAnswerCountMapper.getByPhone(phone);
		if (count == null || count.getAnswerCount() < properties.getPeopleAnswerCount()) {
			return true;
		}
		
		return false;
	}
	
	/**
	 * 保存用户
	 * @param people
	 */
	public  void saveUser(TbMarkPeople people){
//		TbMarkPeople exist = null;
//		exist = tbMarkPeopleMapper.getByPhone(people.getPhone());
//		people.setPhone(exist.getPhone());
		tbMarkPeopleMapper.insert(people);
	}

	public void updateUserInfo(TbMarkPeople people){
		tbMarkPeopleMapper.update(people);
	}


//	public void saveUser(TbMarkPeople people) {
//		TbMarkPeople exist = null;
//		if (people.getPhone() != null) {
//			exist = tbMarkPeopleMapper.getByPhone(people.getPhone());
//			if (exist == null) {
//				tbMarkPeopleMapper.insert(people);
//			} else {
//				people.setId(exist.getId());
//				tbMarkPeopleMapper.update(people);
////				tbMarkPeopleMapper.insert(people);
//			}
//		} else if (people.getId() != null) {
//			tbMarkPeopleMapper.update(people);
////			tbMarkPeopleMapper.insert(people);
//
//		} else {
//			tbMarkPeopleMapper.insert(people);
//		}
//	}

	/**
	 * 读取指定目录下的文件内容
	 * @param name
	 * @param os
	 * @throws Exception
	 */

	public void readFileByName(String name, OutputStream os) throws Exception {
		String filePath = properties.getVoiceLocation();
		if (filePath == null || filePath.equals("")) {
			throw new RuntimeException("请在启动参数或配置文件中指定音频文件位置");
		}
		
		filePath = filePath  + "/" + name;
		File file = new File(filePath);
		if (!file.exists()) {
			throw new RuntimeException("文件'" + filePath + "'不存在");
		}
		
		StreamUtils.copy(Files.newInputStream(Paths.get(filePath)), os);
	}
	
	/**
	 * 获取指定目录下的所有文件，不包括子目录
	 * @param path
	 * @return
	 */
	public List<String> getFileList(String path) {
		File p = new File(path);
		if (p == null || !p.exists()) {
			throw new RuntimeException("目录" + path + "不存在");
		}
		
		List<String> fileList = new ArrayList<>();
		if (p.listFiles() == null) {
			return fileList;
		}
		
		for (File f: p.listFiles()) {
			if (f.isFile()) {
				fileList.add(f.getName());
			}
		}
		
		return fileList;
	}
	
	/**
	 * 获取 wav 文件的播放时长
	 * @param wavFile
	 * @return
	 */
	public Float getWavDuration(File wavFile) {
		try {
			AudioInputStream is = AudioSystem.getAudioInputStream(wavFile);
			AudioFormat af = is.getFormat();
			long fileLength = wavFile.length();
			int frameSize = af.getFrameSize();
			float frameRate = af.getFrameRate();
			float duration = fileLength / (frameSize * frameRate);
			
			return duration;
		} catch(Exception e) {
			e.printStackTrace();
			return 0F;
		}
	}
}  
